Make event-indicator a link to the events page, with new events highlighted.

Currently it works as a reload button, but it gives you nothing but
dismissing the indicator unless you are on the events page, and in any
case you have no idea which events are newly created.

With this change, clicking the indicator takes you to the events page on
which newly created events are highlighted.

Akinori MUSHA 10 anos atrás
pai
commit
38907aea9b

+ 12 - 10
app/assets/javascripts/components/worker-checker.js.coffee

@@ -1,10 +1,15 @@
1 1
 $ ->
2
-  firstEventCount = null
2
+  sinceId = null
3 3
   previousJobs = null
4 4
 
5 5
   if $(".job-indicator").length
6 6
     check = ->
7
-      $.getJSON "/worker_status", (json) ->
7
+      query =
8
+        if sinceId?
9
+          '?since_id=' + sinceId
10
+        else
11
+          ''
12
+      $.getJSON "/worker_status" + query, (json) ->
8 13
         for method in ['pending', 'awaiting_retry', 'recent_failures']
9 14
           count = json[method]
10 15
           elem = $(".job-indicator[role=#{method}]")
@@ -23,16 +28,17 @@ $ ->
23 28
             if elem.is(":visible")
24 29
               elem.tooltip('destroy').fadeOut()
25 30
 
26
-        firstEventCount = json.event_count unless firstEventCount?
27
-        if firstEventCount? && json.event_count > firstEventCount
31
+        if sinceId? && json.event_count > 0
28 32
           $("#event-indicator").tooltip('destroy').
29
-                                tooltip(title: "Click to reload", delay: 0, placement: "bottom", trigger: "hover").
33
+                                tooltip(title: "Click to see the events", delay: 0, placement: "bottom", trigger: "hover").
34
+                                find('a').attr(href: json.events_url).end().
30 35
                                 fadeIn().
31 36
                                 find(".number").
32
-                                text(json.event_count - firstEventCount)
37
+                                text(json.event_count)
33 38
         else
34 39
           $("#event-indicator").tooltip('destroy').fadeOut()
35 40
 
41
+        sinceId ?= json.max_id
36 42
         currentJobs = [json.pending, json.awaiting_retry, json.recent_failures]
37 43
         if document.location.pathname == '/jobs' && $(".modal[aria-hidden=false]").length == 0 && previousJobs? && previousJobs.join(',') != currentJobs.join(',')
38 44
           $.get '/jobs', (data) =>
@@ -42,7 +48,3 @@ $ ->
42 48
         window.workerCheckTimeout = setTimeout check, 2000
43 49
 
44 50
     check()
45
-
46
-  $("#event-indicator a").on "click", (e) ->
47
-    e.preventDefault()
48
-    window.location.reload()

+ 14 - 0
app/assets/stylesheets/tables.css.scss

@@ -20,6 +20,20 @@
20 20
   }
21 21
 }
22 22
 
23
+.table-striped > tbody > tr.hl {
24
+  &:nth-child(odd) {
25
+    > td, > th {
26
+      background-color: #ffeecc;
27
+    }
28
+  }
29
+
30
+  &:nth-child(even) {
31
+    > td, > th {
32
+      background-color: #f9e8c6;
33
+    }
34
+  }
35
+}
36
+
23 37
 table.events {
24 38
   .payload {
25 39
     color: #999;

+ 27 - 7
app/controllers/worker_status_controller.rb

@@ -1,12 +1,32 @@
1 1
 class WorkerStatusController < ApplicationController
2 2
   def show
3
-    start = Time.now.to_f
4
-    render :json => {
5
-        :pending => Delayed::Job.where("run_at <= ? AND locked_at IS NULL AND attempts = 0", Time.now).count,
6
-        :awaiting_retry => Delayed::Job.where("failed_at IS NULL AND attempts > 0").count,
7
-        :recent_failures => Delayed::Job.where("failed_at IS NOT NULL AND failed_at > ?", 5.days.ago).count,
8
-        :event_count => current_user.events.count,
9
-        :compute_time => Time.now.to_f - start
3
+    start = Time.now
4
+    events = current_user.events
5
+
6
+    if params[:since_id].present?
7
+      since_id = params[:since_id].to_i
8
+      events = events.where('id > ?', since_id)
9
+    end
10
+
11
+    result = events.select('COUNT(id) AS count', 'MIN(id) AS min_id', 'MAX(id) AS max_id').first
12
+    count, min_id, max_id = result.count, result.min_id, result.max_id
13
+
14
+    case max_id
15
+    when nil
16
+    when min_id
17
+      events_url = events_path(hl: max_id)
18
+    else
19
+      events_url = events_path(hl: "#{min_id}-#{max_id}")
20
+    end
21
+
22
+    render json: {
23
+      pending: Delayed::Job.where("run_at <= ? AND locked_at IS NULL AND attempts = 0", start).count,
24
+      awaiting_retry: Delayed::Job.where("failed_at IS NULL AND attempts > 0").count,
25
+      recent_failures: Delayed::Job.where("failed_at IS NOT NULL AND failed_at > ?", 5.days.ago).count,
26
+      event_count: count,
27
+      max_id: max_id || 0,
28
+      events_url: events_url,
29
+      compute_time: Time.now - start
10 30
     }
11 31
   end
12 32
 end

+ 27 - 0
app/helpers/application_helper.rb

@@ -71,4 +71,31 @@ module ApplicationHelper
71 71
       service_label_text(service)
72 72
     ].join.html_safe, class: "label label-default label-service service-#{service.provider}"
73 73
   end
74
+
75
+  def highlighted?(id)
76
+    (@hl ||=
77
+     case hl = params[:hl].presence
78
+     when nil
79
+       ->x { false }
80
+     when String
81
+       values = hl.split(/,/).flat_map { |i|
82
+         case i
83
+         when /\A(\d+)\z/
84
+           i.to_i
85
+         when /\A(\d+)?-(\d+)?\z/
86
+           ($1 ? $1.to_i : 1)..($2 ? $2.to_i : (1/0.0))
87
+         else
88
+           []
89
+         end
90
+       }
91
+       ->x {
92
+         case x
93
+         when *values
94
+           true
95
+         else
96
+           false
97
+         end
98
+       }
99
+     end)[id]
100
+  end
74 101
 end

+ 3 - 3
app/views/events/index.html.erb

@@ -18,7 +18,7 @@
18 18
 
19 19
         <% @events.each do |event| %>
20 20
           <% next unless event.agent %>
21
-          <tr>
21
+          <%= content_tag :tr, class: (highlighted?(event.id) ? 'hl' : nil) do %>
22 22
             <td><%= link_to event.agent.name, agent_path(event.agent) %></td>
23 23
             <td title='<%= event.created_at %>'><%= time_ago_in_words event.created_at %> ago</td>
24 24
             <td class='payload'><%= truncate event.payload.to_json, :length => 90, :omission => "" %></td>
@@ -29,12 +29,12 @@
29 29
                 <%= link_to 'Delete', event_path(event), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-default" %>
30 30
               </div>
31 31
             </td>
32
-          </tr>
32
+          <% end %>
33 33
         <% end %>
34 34
         </table>
35 35
       </div>
36 36
 
37
-      <%= paginate @events, :theme => 'twitter-bootstrap-3' %>
37
+      <%= paginate @events, params: params.slice(:hl), theme: 'twitter-bootstrap-3' %>
38 38
 
39 39
       <br />
40 40
 

+ 32 - 0
spec/helpers/application_helper_spec.rb

@@ -143,4 +143,36 @@ describe ApplicationHelper do
143 143
       expect(elem).to be_a Nokogiri::XML::Element
144 144
     end
145 145
   end
146
+
147
+  describe '#highlighted?' do
148
+    it 'understands hl=6-8' do
149
+      stub(params).[](:hl) { '6-8' }
150
+      expect((1..10).select { |i| highlighted?(i) }).to eq [6, 7, 8]
151
+    end
152
+
153
+    it 'understands hl=1,3-4,9' do
154
+      stub(params).[](:hl) { '1,3-4,9' }
155
+      expect((1..10).select { |i| highlighted?(i) }).to eq [1, 3, 4, 9]
156
+    end
157
+
158
+    it 'understands hl=8-' do
159
+      stub(params).[](:hl) { '8-' }
160
+      expect((1..10).select { |i| highlighted?(i) }).to eq [8, 9, 10]
161
+    end
162
+
163
+    it 'understands hl=-2' do
164
+      stub(params).[](:hl) { '-2' }
165
+      expect((1..10).select { |i| highlighted?(i) }).to eq [1, 2]
166
+    end
167
+
168
+    it 'understands hl=-' do
169
+      stub(params).[](:hl) { '-' }
170
+      expect((1..10).select { |i| highlighted?(i) }).to eq [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
171
+    end
172
+
173
+    it 'is OK with no hl' do
174
+      stub(params).[](:hl) { nil }
175
+      expect((1..10).select { |i| highlighted?(i) }).to be_empty
176
+    end
177
+  end
146 178
 end